

#include "touch_800x480.h"

volatile TouchStructure touchInfo; 			// 触摸信息结构体，在函数 Touch_Scan() 里被调用，存储触摸数据
volatile static uint8_t Modify_Flag = 0;	// 坐标数据修改标志位


/*************************************************************************************************************************************
*	函 数 名:	GT9XX_Reset
*	入口参数:	无
*	返 回 值:	无
*	函数功能:	复位GT911
*	说    明:	复位GT911，决定芯片的IIC地址，设定为0xBA/0xBB
************************************************************************************************************************************/

void GT9XX_Reset(void)
{
	Touch_INT_Out();	// 将INT引脚设置为输出

	// 设定初始状态
	HAL_GPIO_WritePin(Touch_INT_PORT,Touch_INT_PIN,GPIO_PIN_RESET);  // INT引脚输出低电平
	HAL_GPIO_WritePin(Touch_RST_PORT,Touch_RST_PIN,GPIO_PIN_SET);    // RST引脚输出高电平
	Touch_IIC_Delay(10000);

	// 开始执行复位
	//	INT引脚保持在低电平，触摸芯片地址设定为0XBA/0XBB
	HAL_GPIO_WritePin(Touch_RST_PORT,Touch_RST_PIN,GPIO_PIN_RESET); // 拉低复位引脚，此时芯片执行复位
	Touch_IIC_Delay(150000);			// 延时
	HAL_GPIO_WritePin(Touch_RST_PORT,Touch_RST_PIN,GPIO_PIN_SET);			// 拉高复位引脚，复位结束
	Touch_IIC_Delay(350000);			// 延时
	Touch_INT_In();						// INT引脚转为输入模式
	Touch_IIC_Delay(20000);				// 延时

}

/*************************************************************************************************************************************
*	函 数 名:	GT9XX_WriteHandle
*	入口参数:	addr - 要操作的寄存器
*	返 回 值:	SUCCESS - 操作成功
*					ERROR	  - 操作失败
*	函数功能:	GT9XX 写句柄
*	说    明:	对指定的寄存器执行写操作
************************************************************************************************************************************/

uint8_t GT9XX_WriteHandle (uint16_t addr)
{
	uint8_t status;		// 状态标志位

	Touch_IIC_Start();	// 启动IIC通信
	if( Touch_IIC_WriteByte(GT9XX_IIC_WADDR) == ACK_OK ) //写入器件指令
	{
		if( Touch_IIC_WriteByte((uint8_t)(addr >> 8)) == ACK_OK ) //写入16位地址
		{
			if( Touch_IIC_WriteByte((uint8_t)(addr)) != ACK_OK )
			{
				status = ERROR;	// 操作失败
			}
		}
	}
	status = SUCCESS;	// 操作成功
	return status;
}

/*************************************************************************************************************************************
*	函 数 名:	GT9XX_WriteData
*	入口参数:	addr - 要写入的寄存器
*					value - 要写入的数据
*	返 回 值:	SUCCESS - 操作成功
*					ERROR	  - 操作失败
*	函数功能:	GT9XX 写一字节数据
*	说    明:	向指定的寄存器写入一字节数据
************************************************************************************************************************************/

uint8_t GT9XX_WriteData (uint16_t addr,uint8_t value)
{
	uint8_t status;

	Touch_IIC_Start(); //启动IIC通讯

	if( GT9XX_WriteHandle(addr) == SUCCESS)	//写入要操作的寄存器
	{
		if (Touch_IIC_WriteByte(value) != ACK_OK) //写入数据
		{
			status = ERROR;
		}
	}
	Touch_IIC_Stop(); // 停止通讯

	status = SUCCESS;	// 写入成功
	return status;
}

/*************************************************************************************************************************************
*	函 数 名:	GT9XX_WriteReg
*	入口参数:	addr - 要写入的寄存器首地址首地址
*					cnt  - 数据长度
*					value - 要写入的数组数据
*	返 回 值:	SUCCESS - 操作成功
*					ERROR	  - 操作失败
*	函数功能:	GT9XX 写寄存器
*	说    明:	向芯片的寄存器里写入指定长度的数据
************************************************************************************************************************************/

uint8_t GT9XX_WriteReg (uint16_t addr, uint8_t cnt, uint8_t *value)
{
	uint8_t status;
	uint8_t i;

	Touch_IIC_Start();

	if( GT9XX_WriteHandle(addr) == SUCCESS) 	// 写入要操作的寄存器
	{
		for(i = 0 ; i < cnt; i++)			 	// 循环
		{
			Touch_IIC_WriteByte(value[i]);	// 写入数据
		}
		Touch_IIC_Stop();		// 停止IIC通信
		status = SUCCESS;		// 写入成功
	}
	else
	{
		Touch_IIC_Stop();		// 停止IIC通信
		status = ERROR;		// 写入失败
	}
	return status;
}

/*************************************************************************************************************************************
*	函 数 名:	GT9XX_ReadReg
*	入口参数:	addr - 要读取的寄存器首地址首地址
*					cnt  - 数据长度
*					value - 要读取的数组数据
*	返 回 值:	SUCCESS - 操作成功
*					ERROR	  - 操作失败
*	函数功能:	GT9XX 读寄存器
*	说    明:	从芯片的寄存器里读取指定长度的数据
************************************************************************************************************************************/

uint8_t GT9XX_ReadReg (uint16_t addr, uint8_t cnt, uint8_t *value)
{
	uint8_t status;
	uint8_t i;

	status = ERROR;
	Touch_IIC_Start();		// 启动IIC通信

	if( GT9XX_WriteHandle(addr) == SUCCESS) //写入要操作的寄存器
	{
		Touch_IIC_Start(); //重新启动IIC通讯

		if (Touch_IIC_WriteByte(GT9XX_IIC_RADDR) == ACK_OK)	// 发送读指令
		{
			for(i = 0 ; i < cnt; i++)	// 循环
			{
				if (i == (cnt - 1))
				{
					value[i] = Touch_IIC_ReadByte(0);	// 读取最后一个数据时，发送 非应答信号
				}
				else
				{
					value[i] = Touch_IIC_ReadByte(1);	// 发送应答信号
				}
			}
			Touch_IIC_Stop();	// 停止IIC通信
			status = SUCCESS;
		}
	}
	Touch_IIC_Stop();	// 停止IIC通信
	return (status);
}

/*************************************************************************************************************************************
*	函 数 名: PanelRecognition
*	入口参数: 无
*	返 回 值: 无
*	函数功能: 识别屏幕的版本
*	说    明: 在 RGB070M1-800*480 V1.1 之前的硬件版本里，触摸屏的分辨率为1024*600，
*				 为了兼容旧的机器，需要进行判断处理，旧版的RST和INT引脚并没有连接到主板，
*				 因此可以根据这两个引脚的电平状态来识别，此段代码只对旧版本7寸屏有作用，
*				 大尺寸触摸屏请忽略此处
************************************************************************************************************************************/

void	PanelRecognition (void)
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};

	Touch_INT_CLK_ENABLE;	//初始化IO口时钟
	Touch_RST_CLK_ENABLE;


	GPIO_InitStruct.Mode  = GPIO_MODE_INPUT;      		// 输入模式
	GPIO_InitStruct.Pull  = GPIO_PULLDOWN;		 			// 下拉模式
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;    	// 速度等级
	GPIO_InitStruct.Pin   = Touch_INT_PIN ;  				// 初始化 INT 引脚

	HAL_GPIO_Init(Touch_INT_PORT, &GPIO_InitStruct);

	GPIO_InitStruct.Pin  = Touch_RST_PIN; 					// RST
	HAL_GPIO_Init(Touch_RST_PORT, &GPIO_InitStruct);

	Touch_IIC_Delay(4000);		// 延时

	// 旧版本的RST和INT引脚并没有连接到主板，因此可以根据这两个引脚的电平状态来识别
	// 新版本的硬件则触摸屏引脚都有连接
	if( (HAL_GPIO_ReadPin(Touch_RST_PORT,Touch_RST_PIN) != 1) && (HAL_GPIO_ReadPin(Touch_INT_PORT,Touch_INT_PIN) != 1)  )
	{
		// 在 V1.1 之前的硬件版本里，触摸屏的分辨率为1024*600，为了兼容旧的机器，需要进行判断处理
		// 该标志位标志需要根据判断是否需要对坐标修改采集到的寄存器数据
		// 此段代码只对旧版本7寸屏有作用，大尺寸触摸屏请忽略此处
		Modify_Flag	= 1;
	}
}

/*************************************************************************************************************************************
*	函 数 名: Touch_Init
*	入口参数: 无
*	返 回 值: SUCCESS  - 初始化成功
*            ERROR 	 - 触摸屏未检测到触摸IC
*	函数功能: 触摸IC初始化，读取对应信息并到串口
*	说    明: 初始化触摸屏
************************************************************************************************************************************/

uint8_t Touch_Init(void)
{
	uint8_t GT9XX_Info[11];	// 存储触摸IC信息
	uint8_t cfgVersion = 0;	// 触摸屏配置版本


	// 识别屏幕的版本，对 RGB070M1-800*480 V1.1以及之后硬件版本屏幕忽略此段代码
	// 此段代码只对旧版本7寸屏有作用，大尺寸触摸屏请忽略此处
	PanelRecognition();

	Touch_IIC_GPIO_Config(); 	// 初始化IIC引脚
	GT9XX_Reset();					// 复位IC

	GT9XX_ReadReg (GT9XX_ID_ADDR,11,GT9XX_Info);		// 读取触摸IC信息
	GT9XX_ReadReg (GT9XX_CFG_ADDR,1,&cfgVersion);	// 读取触摸屏配置版本

	if( GT9XX_Info[0] == '9' )	//判断第一个字符是否为 9
	{
		printf("Touch ID: GT%.4s \r\n",GT9XX_Info);	//打印触摸芯片的ID
		printf("Firmware Ver: 0X%.4x\r\n",(GT9XX_Info[5]<<8) + GT9XX_Info[4]);	// 芯片固件版本
		printf("Touch Resolution: %d * %d\r\n",(GT9XX_Info[7]<<8) + GT9XX_Info[6],(GT9XX_Info[9]<<8) +GT9XX_Info[8]);	// 当前触摸分辨率
		printf("Config Ver: 0X%.2x \r\n",cfgVersion);	// 触摸屏配置版本

/*---------版本识别RGB070M1-800*480 V1.1以及之后硬件版本大尺寸触摸屏请忽略此段代码-----*/

		// 在 RGB070M1-800*480 V1.1 之前的硬件版本里，触摸屏的分辨率为1024*600，为了兼容旧的机器，需要进行判断处理
		// 该标志位标志需要根据判断是否需要对坐标修改采集到的寄存器数据
		if( ( (GT9XX_Info[7]<<8) + GT9XX_Info[6] ) != 1024 )		// 判断触摸屏的X分辨率是否为1024
		{
			Modify_Flag	= 1;
		}
		else if( ( (GT9XX_Info[7]<<8) + GT9XX_Info[6] ) == 1024 )	// 触摸屏的X分辨率为1024
		{
			Modify_Flag	= 0;	// 置0标志位，不需要转换
		}

/*-------------------------------------------------------------------------------------------------*/
		return SUCCESS;
	}
	else
	{
		printf("Touch Error\r\n");	//触摸屏未检测到触摸IC
		return ERROR;
	}

}

/*************************************************************************************************************************************
*	函 数 名: Touch_Scan
*	入口参数: 无
*	返 回 值: 无
*	函数功能: 触摸扫描
*	说    明: 在主函数里循环调用该函数，可以实时检测触摸状态，触摸信息存储在 touchInfo 结构体
************************************************************************************************************************************/

void Touch_Scan(void)
{
 	uint8_t  touchData[2 + 8 * TOUCH_MAX ]; 		// 用于存储触摸数据
	uint8_t  i = 0;

	GT9XX_ReadReg (GT9XX_READ_ADDR,2 + 8 * TOUCH_MAX ,touchData);	// 读数据
	GT9XX_WriteData (GT9XX_READ_ADDR,0);									// 清除触摸芯片的寄存器标志位
	touchInfo.num = touchData[0] & 0x0f;									// 取得当前的触点个数

	if ( (touchInfo.num >= 1) && (touchInfo.num <=5) ) 	// 触点个数在 1-5 之间时
	{
		for(i=0;i<touchInfo.num;i++)		// 取相应的触点坐标
		{
			touchInfo.y[i] = (touchData[5+8*i]<<8) | touchData[4+8*i];	// 获取Y坐标
			touchInfo.x[i] = (touchData[3+8*i]<<8) | touchData[2+8*i];	// 获取X坐标

/*---------更新1024*600分辨率，坐标直接使用不需要转换-----*/

			// 当前LCD已更改为1024*600分辨率，坐标数据直接使用不需要转换
			// 用Modify_Flag标志位来判断触摸屏是否与LCD分辨率匹配
			// Modify_Flag = 0 时，坐标数据和屏幕正好对应的直接显示
			// Modify_Flag = 1 时，需要坐标缩放变换才能在800*480下正确显示
			if( Modify_Flag == 1)
			{
				touchInfo.y[i] *= 0.8;		// 将1024*600分辨率的触摸坐标缩放到800*480的分辨率
				touchInfo.x[i] *= 0.78;		// 将1024*600分辨率的触摸坐标缩放到800*480的分辨率
			}
/*-------------------------------------------------------------------------------------------------*/

		}
		touchInfo.flag = 1;	// 触摸标志位置1，有触摸动作产生
	}
	else
	{
		touchInfo.flag = 0;	// 触摸标志位置0，无触摸动作
	}
}

/*************************************************************************************************************************************************************************************************FFKE****/


